package com.kunlun.basedata.limit.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.kunlun.basedata.limit.dao.IAuthorizeDao;
import com.kunlun.basedata.limit.model.AuthorizeModel;
import com.kunlun.basedata.limit.model.po.AuthorizePo;
import com.kunlun.basedata.limit.model.po.CorrelatePo;
import com.kunlun.basedata.limit.model.vo.AuthorizeVo;
import com.kunlun.basedata.limit.model.vo.CorrelateVo;
import com.kunlun.basedata.limit.model.vo.UserRelateVo;
import com.kunlun.basedata.limit.service.IAuthorizeService;
import com.kunlun.basedata.limit.service.ICorrelateService;
import com.kunlun.basedata.user.model.UserModel;
import com.kunlun.basedata.user.service.IUserService;
import com.kunlun.basedata.utils.CommonUtil;
import com.kunlun.common.model.Page;
import com.kunlun.common.utils.TreeUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 岗位业务Service类
 */
@Service
@Transactional
public class AuthorizeService implements IAuthorizeService {

    private final Logger logger = LogManager.getLogger();

    @Autowired
    private ICorrelateService correlateService;
    @Autowired
    private IAuthorizeDao authorizeDao;
    @Autowired
    private IUserService userService;

    @Override
    public Page<AuthorizeVo> getAuthorizePage(CorrelatePo correlatePo, int currentPage, int pageSize) throws Exception {
        int startIndex = (currentPage - 1) * pageSize;
        Map<String, Object> queryMap = CommonUtil.packageQueryMap(correlatePo, 0, 0);

        List<AuthorizeVo> authorizeModels = null, authorizeVoList = new ArrayList<>();
        if (!ObjectUtils.isEmpty(correlatePo.getType()) && "0".equals(correlatePo.getType())) {
            authorizeModels = authorizeDao.getAuthorizeRoleList(queryMap);
        } else if (!ObjectUtils.isEmpty(correlatePo.getType()) && "1".equals(correlatePo.getType())) {
            authorizeModels = authorizeDao.getAuthorizeOrganizeList(queryMap);
        } else if (!ObjectUtils.isEmpty(correlatePo.getType()) && "2".equals(correlatePo.getType())) {
            authorizeModels = authorizeDao.getAuthorizeApplicationList(queryMap);
        }

        Map<String, List<AuthorizeVo>> authorizeMap = authorizeModels.stream().collect(Collectors.groupingBy(AuthorizeVo::getTargetId));
        for (Map.Entry<String, List<AuthorizeVo>> map : authorizeMap.entrySet()) {
            authorizeVoList.addAll(TreeUtil.buildTree(map.getValue()));
        }

        int total = authorizeVoList.size();
        int maxIndex = startIndex + pageSize;
        List<AuthorizeVo> authorizeVos = authorizeVoList.subList(startIndex, maxIndex > total ? total : maxIndex);
        authorizeVos = authorizeVos.stream().peek(obj -> obj.setId(CommonUtil.generateUUID())).collect(Collectors.toList());
        Page<AuthorizeVo> page = new Page<>();
        page.setTotal(total);
        page.setRecords(authorizeVos);
        return page;
    }

    @Override
    public void addAuthorize(AuthorizePo authorizePo) throws Exception {
        boolean flag = "1".equals(authorizePo.getType());
        Map<String, CorrelateVo> correlateMap = null;
        if (flag) {
            List<CorrelateVo> correlateList = correlateService.getCorrelateList(new HashMap<>());
            correlateMap = correlateList.stream().collect(Collectors.toMap(CorrelateVo::getLongCode, Function.identity()));
        }
        List<String> subjectCodes = JSONArray.parseArray(authorizePo.getSubjectCode(), String.class);
        Map<String, String> subjectCodeMap = new HashMap<>();
        for (String subjectCode : subjectCodes) {
            String[] codes = subjectCode.split("_");
            for (String code : codes) {
                int index = subjectCode.indexOf(code);
                subjectCodeMap.put(subjectCode.substring(0, index + code.length()), code);
            }
        }

        for (Map.Entry<String, String> subjectMap : subjectCodeMap.entrySet()) {
            String[] codes = subjectMap.getKey().split("_");
            AuthorizeModel authorizeModel = new AuthorizeModel();
            authorizeModel.setId(CommonUtil.generateUUID());
            authorizeModel.setType(Integer.valueOf(authorizePo.getType()));
            authorizeModel.setTargetId(authorizePo.getTargetId());
            if (flag) {
                CorrelateVo correlateVo = correlateMap.getOrDefault(subjectMap.getKey(), new CorrelateVo());
                authorizeModel.setSubjectId(correlateVo.getSubjectId());
                authorizeModel.setVirtualId(correlateVo.getVirtualId());
                authorizeModel.setVirtualCode(correlateVo.getVirtualCode());
                authorizeModel.setVirtualParent(correlateVo.getVirtualParent());
            } else {
                authorizeModel.setSubjectId(subjectMap.getValue());
            }
            authorizeDao.addAuthorize(authorizeModel);
        }
    }

    @Override
    public UserRelateVo getAuthorizeByUser(String tenantId, String appId, String userId) throws Exception {
        UserModel userModel = userService.getUserById(userId);

        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("userId", userId);

        UserRelateVo userRelateVo = correlateService.getCorrelateByUser(tenantId, appId, userId);
//        List<RelateNodeVo> roleList = userRelateVo.getRoleList();
//        Set<String> roleIdSets = roleList.stream().map(obj -> obj.getId()).collect(Collectors.toSet());
//
//        queryMap.put("targetIds", roleIdSets);
//        List<RelateNodeVo> roleLimitList = new ArrayList<>();
//        List<RelateNodeVo> limitRoleModels = authorizeDao.getLimitRoleList(queryMap);
//        Map<String, List<RelateNodeVo>> roleLimitMap = limitRoleModels.stream().collect(Collectors.groupingBy(RelateNodeVo::getTargetId));
//        for (Map.Entry<String, List<RelateNodeVo>> roleMap : roleLimitMap.entrySet()) {
//            List<RelateNodeVo> limitRoleList = TreeUtil.buildTree(roleMap.getValue());
//            roleLimitList.addAll(limitRoleList);
//        }
//
//        List<RelateNodeVo> postList = userRelateVo.getPostList();
//        Set<String> postIdSets = postList.stream().map(obj -> obj.getId()).collect(Collectors.toSet());
//        queryMap.put("targetIds", postIdSets);
//        List<RelateNodeVo> limitDepartmentModels = authorizeDao.getLimitDepartmentList(queryMap);
//        Map<String, List<RelateNodeVo>> departmentLimitMap = limitDepartmentModels.stream().collect(Collectors.groupingBy(RelateNodeVo::getTargetId));
//
//        List<RelateNodeVo> limitPostModels = authorizeDao.getLimitPostList(queryMap);
//        Map<String, List<RelateNodeVo>> postLimitMap = limitPostModels.stream().collect(Collectors.groupingBy(RelateNodeVo::getTargetId));
//
//        List<RelateNodeVo> postLimitList = new ArrayList<>();
//        List<RelateNodeVo> limitCompanyModels = authorizeDao.getLimitCompanyList(queryMap);
//        Map<String, List<RelateNodeVo>> companyLimitMap = limitCompanyModels.stream().collect(Collectors.groupingBy(RelateNodeVo::getTargetId));
//        for (Map.Entry<String, List<RelateNodeVo>> companyMap : companyLimitMap.entrySet()) {
//            List<RelateNodeVo> values = companyMap.getValue();
//            List<RelateNodeVo> relateNodeVos = TreeUtil.buildTree(values);
//            List<RelateNodeVo> departmentLimits = departmentLimitMap.getOrDefault(companyMap.getKey(), new ArrayList<>());
//            Map<String, List<RelateNodeVo>> limitDepartmentMap = departmentLimits.stream().collect(Collectors.groupingBy(RelateNodeVo::getLongCode));
//
//            List<RelateNodeVo> postLimits = postLimitMap.getOrDefault(companyMap.getKey(), new ArrayList<>());
//            Map<String, List<RelateNodeVo>> limitPostMap = postLimits.stream().collect(Collectors.groupingBy(RelateNodeVo::getLongCode));
//            TreeUtil.addTreeNode(relateNodeVos, limitDepartmentMap);
//            TreeUtil.addTreeNode(relateNodeVos, limitPostMap);
//            postLimitList.addAll(relateNodeVos);
//        }

        userRelateVo.setUserId(userId);
        userRelateVo.setUserName(userModel.getUserName());
//        userRelateVo.setRolelimitList(roleLimitList);
//        userRelateVo.setPostLimieList(postLimitList);
        return userRelateVo;
    }
}
